import threading
import time
from pickle import dumps, loads
import random
import zmq
from zhelpers import zpipe


MAX_ALLOWWED_DELAY = 1.0


def subscriber(pipe):
    ctx = zmq.Context.instance()
    sub = ctx.socket(zmq.SUB)
    sub.setsockopt(zmq.SUBSCRIBE, b'')
    sub.connect("tcp://localhost:5556")

    while True:
        clock = loads(sub.recv())
        if time.time() - clock > MAX_ALLOWWED_DELAY:
            print("E: subscriber cannot keep up,aborting")
            break

        time.sleep(1e-3 * (1 + 2*random.random()))
    pipe.send(b"gone and died")


def publisher(pipe):
    ctx = zmq.Context.instance()
    pub = ctx.socket(zmq.PUB)
    pub.bind("tcp://*:5556")

    while True:
        pub.send(dumps(time.time()))
        try:
            signal = pipe.recv(zmq.DONTWAIT)
        except zmq.ZMQError as e:
            if e.errno == zmq.EAGAIN:
                pass
            else:
                raise
        else:
            break
        time.sleep(1e-3)


def main():
    ctx = zmq.Context.instance()
    pub_pipe, pub_peer = zpipe(ctx)
    sub_pipe, sub_peer = zpipe(ctx)

    pub_thread = threading.Thread(target=publisher, args=(pub_peer,))
    pub_thread.daemon = True
    pub_thread.start()

    sub_thread = threading.Thread(target=subscriber, args=(sub_peer,))
    sub_thread.daemon = True
    sub_thread.start()

    sub_pipe.recv()
    pub_pipe.send(b"break")
    time.sleep(0.1)


if __name__ == "__main__":
    main()
